package cn.baddonkey.superqueryjavasdk.bean;

import cn.baddonkey.superqueryjavasdk.config.ModuleConfigDatasource;
import cn.baddonkey.superqueryjavasdk.config.ModuleConfigJson;
import cn.baddonkey.superqueryjavasdk.constant.JsonClassNameConstant;
import cn.baddonkey.superqueryjavasdk.exception.NoJsonDependencyException;
import cn.baddonkey.superqueryjavasdk.exception.NotImplementedException;
import cn.baddonkey.superqueryjavasdk.interfaces.ModuleConfigAssembleInterface;
import cn.baddonkey.superqueryjavasdk.interfaces.ModuleConfigQueryInterface;
import cn.baddonkey.superqueryjavasdk.interfaces.ModuleConvertInterface;
import cn.baddonkey.superqueryjavasdk.interfaces.ModuleSqlProcessInterface;
import cn.baddonkey.superqueryjavasdk.interfaces.impl.ModuleConfigAssemble;
import cn.baddonkey.superqueryjavasdk.interfaces.impl.ModuleConfigQuery;
import cn.baddonkey.superqueryjavasdk.interfaces.impl.ModuleConvert;
import cn.baddonkey.superqueryjavasdk.interfaces.impl.ModuleSqlProcess;
import cn.baddonkey.superqueryjavasdk.json.*;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SqlProcessorFactory {
    @Bean
    @ConditionalOnMissingBean(ModuleConfigQueryInterface.class)
    public ModuleConfigQueryInterface moduleConfigQueryInterface(ModuleConfigDatasource moduleConfigDatasource) {
        return new ModuleConfigQuery(moduleConfigDatasource);
    }

    @Bean
    @ConditionalOnMissingBean(ModuleConfigAssembleInterface.class)
    public ModuleConfigAssembleInterface moduleConfigAssembleInterface() {
        return new ModuleConfigAssemble();
    }

    @Bean
    @ConditionalOnMissingBean(ModuleConvertInterface.class)
    public ModuleConvertInterface moduleConvertInterface(ModuleConfigJson moduleConfigJson) {
        ModuleConfigJson.JsonProcessorType jsonProcessorType = moduleConfigJson.getType();
        if (jsonProcessorType != null) {
            JsonParser jsonParser;
            if (jsonProcessorType == ModuleConfigJson.JsonProcessorType.FASTJSON) {
                try {
                    Class.forName(JsonClassNameConstant.FASTJSON);
                } catch (ClassNotFoundException e) {
                    throw new NoJsonDependencyException(ModuleConfigJson.JsonProcessorType.FASTJSON.getTypeName());
                }
                jsonParser = new FastjsonParser();
            } else if (jsonProcessorType == ModuleConfigJson.JsonProcessorType.JACKSON) {
                try {
                    Class.forName(JsonClassNameConstant.JACKSON);
                } catch (ClassNotFoundException e) {
                    throw new NoJsonDependencyException(ModuleConfigJson.JsonProcessorType.JACKSON.getTypeName());
                }
                jsonParser = new JacksonParser();
            } else if (jsonProcessorType == ModuleConfigJson.JsonProcessorType.GSON) {
                try {
                    Class.forName(JsonClassNameConstant.GSON);
                } catch (ClassNotFoundException e) {
                    throw new NoJsonDependencyException(ModuleConfigJson.JsonProcessorType.GSON.getTypeName());
                }
                jsonParser = new GsonParser();
            } else {
                jsonParser = new NoneParser();
            }
            return new ModuleConvert(jsonParser);
        }
        return new ModuleConvert();
    }

    @Bean
    @ConditionalOnMissingBean(ModuleSqlProcessInterface.class)
    public ModuleSqlProcessInterface moduleSqlProcessInterface() {
        return new ModuleSqlProcess();
    }

    @Bean
    public SqlProcessor sqlProcessor(
            ModuleConfigQueryInterface moduleConfigQueryInterface,
            ModuleConfigAssembleInterface moduleConfigAssembleInterface,
            ModuleConvertInterface moduleConvertInterface,
            ModuleSqlProcessInterface moduleSqlProcessInterface
    ) {
        if (moduleSqlProcessInterface instanceof ModuleSqlProcess) {
            throw new NotImplementedException(ModuleSqlProcessInterface.class);
        }
        SqlProcessor sqlProcessor = new SqlProcessor();
        sqlProcessor.setModuleConfigQuery(moduleConfigQueryInterface);
        sqlProcessor.setModuleConfigAssemble(moduleConfigAssembleInterface);
        sqlProcessor.setModuleSqlProcess(moduleSqlProcessInterface);
        sqlProcessor.setModuleConvert(moduleConvertInterface);
        return sqlProcessor;
    }
}
